
/*
*
*	The Gimme Javascript Library by Stephen Stchur
*	"A truly customizable Javascript library"
*
*	Copyright (c) Microsoft Corporation.  All rights reserved.
*
*/

var Gimme = function()
{
	// private "classes"
	function GimmeObject(collection)
	{
		Array.prototype.push.apply(this, collection);
	}
	augmentProto(GimmeObject, 
	{	
		length: Array.prototype.length,
		entities: function()
		{
			return Array.prototype.slice.apply(this);
		},		
		sort: function(sortFn)
		{
			Array.prototype.sort.call(this, sortFn);
			return this;
		},
		reverse: function()
		{
			Array.prototype.reverse.call(this);
			return this;
		},
		push: function()
		{
			Array.prototype.push.apply(this, arguments);
			return this;
		},
		pop: function()
		{
			var p = Array.prototype.pop.call(this);
			return new GimmeObject([p]);
		},
		shift: function()
		{
			var s = Array.prototype.shift.call(this)
			return new GimmeObject([s]);
		},
		unshift: function()
		{
			Array.prototype.unshift.apply(this, arguments);
			return this;
		},
		slice: function()
		{
			return new GimmeObject(Array.prototype.slice.apply(this, arguments));
		},
		splice: function()
		{
			return new GimmeObject(Array.prototype.splice.apply(this, arguments));
		},
		concat: function(gim)
		{
			return new GimmeObject(Array.prototype.concat.apply(this.entities(), gim.entities && gim.entities() || arguments));
		}
	});
	////
	
	
	// the actual Gimme(..) function
	function Gimme(selector, root)
	{
		if (selector instanceof GimmeObject)
		{
			return selector;
		}

		var entities =
			!selector && []
			|| (root || typeof selector === 'string') && Gimme.query(selector, root)
			|| selector instanceof Array && selector
			|| [ selector ];
		
		return new GimmeObject(entities);
	}		
	////
	
	
	// Gimme Helper namespace
	Gimme.Helper = 
	{
		get_guid: function()
		{
			var counter = 0;
			return function(elem)
			{	
				if (!elem)
				{
					return '';
				}
				if (elem === window)
				{
					return 'win';
				}
				else if (elem === document)
				{
					return 'doc';
				}
				else if (elem.uniqueID)
				{
					return elem.uniqueID;
				}

				var ex = '__$gimme$_guid__';
				if (typeof elem[ex] === 'undefined')
				{
					elem[ex] = ex + counter++;
				}
				return elem[ex];
			}
		}()
	};
	////
	
	
	// Gimme Browser namespace
	Gimme.Browser = function()
	{
		var ua = navigator.userAgent.toLowerCase();
		return {
			is_ie: typeof ActiveXObject !== 'undefined',
			is_opera: typeof window.opera !== 'undefined',
			is_khtml: ua.indexOf('khtml') !== -1,
			is_gecko: ua.indexOf('khtml') === -1 && ua.indexOf('gecko') !== -1,
			is_in_quirks_mode: document.compatMode === 'BackCompat'
		};
	}();
	
	
	// Gimme undefined (safe from any other library purposely or inadvertently overwriting the native undefined value)
	Gimme.undefined = ({})._$gimme$_undefined;
	////
	
	
	// the Gimme extension property
	Gimme.ext = GimmeObject.prototype;
	////
	
	
	// Helper function to augment the prototype of any given instance.
	// This allows the thing being augmented to keep its original constructor property,
	// thereby allowing for type testing via: myInstance.constructor == TheConstructor
	function augmentProto(thing, augmentationObject)
	{
		var key;
		for (key in augmentationObject)
		{
			if (augmentationObject.hasOwnProperty(key))
			{
				thing.prototype[key] = augmentationObject[key];
			}
		}
	}
	////
		
	
	return Gimme;
}();

Gimme.ext.select = function(selector)
{
	return Gimme(selector, this[0]);
};

// map g to Gimme if it hasn't already been taken
if (typeof g === 'undefined')
{
	window.g = Gimme;
}
////
